package jp.co.worksap.ate.gomoku.localai;

import java.util.ArrayList;
import java.util.List;

import jp.co.worksap.ate.gomoku.model.GoPoint;
import jp.co.worksap.ate.gomoku.model.GoState;
import jp.co.worksap.ate.gomoku.model.Goban;

public class LocalAIUtil {
	public static double computeGoScoreForOneSide(Goban goban, GoState goType, int x, int y) {
		double goScore = computeGoScoreForOneSideOneGo(goban, goType, x, y);
		Goban gobanWithoutGo = goban.clone();
		gobanWithoutGo.putGo(x, y, GoState.EMPTY);
		List<GoPoint> coreList = goban.getRelatedCoreGo(x, y, goType);
		double max = goScore;
		for(GoPoint coreGoPoint : coreList) {
			double newScore = computeGoScoreForOneSideOneGo(goban, goType, coreGoPoint.getX(), coreGoPoint.getY());
			double oldScore = computeGoScoreForOneSideOneGo(gobanWithoutGo, goType, coreGoPoint.getX(), coreGoPoint.getY());
			if(Math.abs(newScore - oldScore) > 0.0000001) {
				//When the score changed, shows this go has influence to the core go
				if(newScore > max) {
					max = newScore;
				}
			}
		}
		return max;
	}
	private static double computeGoScoreForOneSideOneGo(Goban goban, GoState goType, int x, int y) {
		if(goban.countContinuation(x, y, 5, goType)>0) {
			return 500000;
		}
		if(goban.countDoubleLive(x, y, 4, goType)>0) {
			return 50000;
		}
		int singleLive4 = goban.countSingleLive(x, y, 4, goType);
		int doubleLive3 = goban.countDoubleLive(x, y, 3, goType);
		int singleLive3 = goban.countSingleLive(x, y, 3, goType);
		int doubleLive2 = goban.countDoubleLive(x, y, 2, goType);
		int singleLive2 = goban.countSingleLive(x, y, 2, goType);
		if(singleLive4>=2) {
			return 50000;
		}
		if(singleLive4>0 && doubleLive3>0) {
			return 50000;
		}
		if(doubleLive3>=2) {
			return 80;
		}
		if(singleLive3>0 && doubleLive3>0) {
			return 70;
		}
		if(singleLive4>0) {
			return 60;
		}
		if(doubleLive3>0) {
			return 50;
		}
		if(doubleLive2>=2) {
			return 40;
		}
		if(singleLive3>0) {
			return 30;
		}
		if(doubleLive2>0) {
			return 20;
		}
		if(singleLive2>0) {
			return 10;
		}
		return 1;
	}
	public static List<GoNode> getAllEmptyGoNode(Goban goban) {
		List<GoNode> resultList = new ArrayList<GoNode>();
		int xSize = goban.getXSize();
		int ySize = goban.getYSize();
		for(int i=0; i<xSize; i++) {
			for(int j=0; j<ySize; j++) {
				if (goban.isEmpty(i, j)) {
					GoNode node = new GoNode(i, j);
					resultList.add(node);
				}
			}
		}
		return resultList;
	}
	public static List<GoNode> getAllValueableEmptyGoNode(Goban goban, int offset) {
		List<GoNode> resultList = new ArrayList<GoNode>();
		int xSize = goban.getXSize();
		int ySize = goban.getYSize();
		for(int i=0; i<xSize; i++) {
			for(int j=0; j<ySize; j++) {
				if (goban.isEmpty(i, j) && isValueablePosition(goban, i, j, offset)) {
					GoNode node = new GoNode(i, j);
					resultList.add(node);
				}
			}
		}
		return resultList;
	}
	private static boolean isValueablePosition(Goban goban, int x, int y, int offset) {
		int xFrom = x - offset;
		if(xFrom<0) xFrom = 0;
		int xTo = x + offset;
		if(xTo>=goban.getXSize()) xTo = goban.getXSize() - 1;
		int yFrom = y - offset;
		if(yFrom<0) yFrom = 0;
		int yTo = y + offset;
		if(yTo>=goban.getYSize()) yTo = goban.getYSize() -1;
		for(int i=xFrom; i<=xTo; i++) {
			for(int j=yFrom; j<=yTo; j++) {
				if(i==x && j==y) {
					continue;
				}
				if(!goban.isEmpty(i, j)) {
					return true;
				}
			}
		}
		return false;
	}
}
